#pragma once

#include <vector>
#include <string>
#include <algorithm>

//网络库底层的缓冲区定义
class Buffer
{
public:
    static const size_t kCheapPrepend = 8; //用于记录数据包的长度
    static const size_t kInitialSize = 1024; //数据包初始化长度
    //static const size_t kInitialSize = 14; //数据包初始化长度
    explicit Buffer(size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend+kInitialSize)
        , readIndex_(kCheapPrepend)
        , writeIndex_(kCheapPrepend)
    {}

    size_t readableBytes() const
    {
        return writeIndex_ - readIndex_;
    }

    size_t writableBytes() const
    {
        return buffer_.size() - writeIndex_;
    }

    //前置的
    size_t prependableBytes() const
    {
        return readIndex_;
    }

    //返回缓冲区中可读数据的起始地址
    const char* peek() const
    {
        return begin() + readIndex_;
    }

    // onMessage string <- Buffer  取回
    void retrieve(size_t len)
    {
        if(len < readableBytes())
        {
            readIndex_+=len; //相当于空闲出了一部分数据(即读取的部分空闲出来了)，用户只读取了可读缓冲区数据的一部分，就是len
        }
        else
        {
            retrieveAll();
        }
    }

    void retrieveAll()
    {
        readIndex_ = writeIndex_ = kCheapPrepend; //相当于删除了readIndex_和writeIndex_之间的的可读数据
    }

    //把onMessage函数上报的BUffer数据，转成string类型的数据返回
    std::string retrieveAllAsString()
    {
        return retrieveAsString(readableBytes()); //应用可读取数据的长度
    }

    std::string retrieveAsString(size_t len)
    {
        std::string result(peek(),len);
        retrieve(len); //上一句把缓冲区可读的数据已经取出来，这里肯定要对readIndex_进行处理
        return result;
    }

    void ensureWritableBytes(size_t len)
    {
        if(writableBytes() < len)
        {
            makeSpace(len); //扩容函数
        }
    }

    //把[data,data+len]内存上的数据添加到writable缓冲区当中
    void append(const char* data, size_t len)
    {
        ensureWritableBytes(len);
        std::copy(data, data+len,beginWrite());
        writeIndex_+=len;
    }

    char* beginWrite()
    {
        return begin() + writeIndex_;
    }

    const char* beginWrite() const
    {
        return begin() + writeIndex_;
    }

    //从fd上读取数据
    ssize_t readFd(int fd,int* saveErrno);
    //通过fd发送数据
    ssize_t writeFd(int fd,int* saveErrno);
private:
    char* begin()
    {
        return &*buffer_.begin(); //vector底层数组首元素的地址，也就是数组的起始地址
    }
    const char* begin() const
    {
        return &*buffer_.begin();
    }

    void makeSpace(size_t len)
    {
        //当前面空闲出来的部分(prependableBytes()-kCheapPrepend)加上可写部分还不够的时候就要resize了
        if(writableBytes()+prependableBytes()<len + kCheapPrepend)
        {
            buffer_.resize(writeIndex_+len);
        }
        else
        {
            size_t readable = readableBytes();
            std::copy(begin()+readIndex_, begin()+writeIndex_,begin()+kCheapPrepend);
            readIndex_=kCheapPrepend;
            writeIndex_=readIndex_+readable;
        }
    }

    std::vector<char> buffer_;
    size_t readIndex_;
    size_t writeIndex_;
};
